﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using t_TestingLibrary;
using HTMLPageScanners;
using t_PivotGeneratorTestHelpers;
using System.IO;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using DeepZoomPivotConstructor.PivotLib;
using System.Diagnostics;

namespace t_HTMLPageScanners
{
    /// <summary>
    /// Test the main page and below scanner.
    /// </summary>
    [TestClass]
    public class t_ScanThisPageAndBelow
    {
        [TestInitialize]
        public void Setup()
        {
            Utilities.MyClassInit();
        }

        [TestCleanup]
        public void Cleanup()
        {
            Utilities.MyClassDone();
        }

        /// <summary>
        /// Helper class that doesn't actually do any rendering as much as hold onto things.
        /// </summary>
        [Export(typeof(IPaperRenderEngine))]
        class DummyRender : IPaperRenderEngine
        {
            public List<string> addressesRequested = new List<string>();

            private Dictionary<string, int> requestTypeCount = new Dictionary<string, int>();

            public IEnumerable<PivotImage> Render(string renderName, string renderAddress)
            {
                Trace.WriteLine("Rendering " + renderName + " - " + renderAddress);
                if (!addressesRequested.Contains(renderAddress))
                {
                    addressesRequested.Add(renderAddress);
                    PivotImage pm = new PivotImage(null);
                    pm.Name = "HSF1";
                    try
                    {
                        pm.Add("More Information", "Main Note Page", new Uri(renderAddress));
                    }
                    catch { }
                    if (!requestTypeCount.Keys.Contains(renderName))
                    {
                        requestTypeCount[renderName] = 0;
                    }
                    requestTypeCount[renderName] += 1;

                    if (SetSubTitle != "" && SetSubTitle != null)
                    {
                        pm.Add("Note Title", SetSubTitle);
                    }
                    yield return pm;
                }
            }

            public int TypeRequestCount(string name)
            {
                if (!requestTypeCount.Keys.Contains(name))
                {
                    return 0;
                }
                return requestTypeCount[name];
            }

            public string SetSubTitle { get; set; }
        }

        [TestMethod]
        public void TestCTor()
        {
            var h = new ScanThisPageAndBelow();
        }


        [TestMethod]
        [ExpectedException(typeof(UriFormatException))]
        public void TestBadRenderAddress()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("ftp://www.bogus.com/doit.html");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestBadRenderAddressNullLength()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("");
        }

        [TestMethod]
        [ExpectedException(typeof(UriFormatException))]
        public void TestBadRenderAddressBadlyFormed()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNowhttp://www.bogus.com/doit.html");
        }

        [TestMethod]
        public void TestSubPageOnly()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestSubPageOnlyRootURLWithSlash()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNow/http://www.bogus.com/");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestSubPageOnlyRootURLWithoutSlash()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNow/http://www.bogus.com");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestMasterAndSubPage()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=true,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(3, results.Count(), "Expected two items back");
            Assert.AreEqual(3, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/doit.html"), "Missing doit.html");
        }

        [TestMethod]
        public void TestMainNotePageAndSubNotePageInfo()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=true,PlotPageScanner=MeNow/http://www.bogus.com/doit.html").ToArray();

            /// Make sure all the main info stuff is right.

            var pmeta = (from pi in results
                        from allpmeta in pi.GetMetadata<PivotMetadataURL>("More Information")
                        where allpmeta.LinkText == "Main Note Page"
                        select allpmeta.LinkUri.OriginalString).ToArray();
            Assert.AreEqual(3, pmeta.Length, "Expected as many links as there were items!");
            foreach (var item in pmeta)
            {
                Assert.AreEqual("http://www.bogus.com/doit.html", item, "Incorrect link discovered!");
            }

            ///
            /// Only two shoudl have plot page - the top level one shouldn't get a seperate entry
            /// since that is a duplicate.
            /// 

            var pmetaSub = (from pi in results
                            from allpmeta in pi.GetMetadata<PivotMetadataURL>("More Information")
                            where allpmeta.LinkText == "Plot Page"
                            select allpmeta.LinkUri.OriginalString).ToArray();
            foreach (var item in pmetaSub)
            {
                Console.WriteLine("Link URI is " + item);
            }
            Assert.AreEqual(2, pmetaSub.Length, "Expected as many links as there were items!");
            foreach (var item in pmetaSub)
            {
                Assert.IsTrue(item == "http://www.bogus.com/dude.html" || item == "http://www.bogus.com/dude2.html", "Incorrect link discovered!");
            }
        }

        [TestMethod]
        public void TestDefaultBehavior()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("HTMLSimpleTableCells"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestCDFMasterHiggsGammaGamma()
        {
            /// 
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\CDFGamma.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=true,PlotPageScanner=MeNow/http://www-cdf.fnal.gov/physics/new/hdg//Results_files/results/hgamgam_jan10/index.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(4, results.Count(), "Expected two items back");
            Assert.AreEqual(4, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
        }

        [TestMethod]
        public void TestCircularReferences()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPagesAndCircularRef.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestNoSidRefs()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPagesAndSidRef.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(2, results.Count(), "Expected two items back");
            Assert.AreEqual(2, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested twice");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude.html"), "Missing dude.html");
            Assert.IsTrue(rd.addressesRequested.Contains("http://www.bogus.com/dude2.html"), "Missing dude2.html");
        }

        [TestMethod]
        public void TestRecursiveWithTopPageTrue()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=true,Recursive=true,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(3, results.Count(), "Expected 3 items back");
            Assert.AreEqual(1, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested once for the top level item");
            Assert.AreEqual(2, rd.TypeRequestCount("MasterHTMLRenderHTMLAndFurther"), "Expected two times recursing on this guy!");
            Assert.IsTrue(rd.addressesRequested.Contains("/PlotPageScanner=MeNow,Recursive=true,UseTopPage=true/http://www.bogus.com/dude.html"), "dude should be recursed once");
            Assert.IsTrue(rd.addressesRequested.Contains("/PlotPageScanner=MeNow,Recursive=true,UseTopPage=true/http://www.bogus.com/dude2.html"), "dude2 should have been recursed once as well");
        }

        [TestMethod]
        public void TestRecursiveWithTopPageFalse()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,Recursive=true,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            Assert.IsNotNull(results, "Expected a non-null value back from the render");
            Assert.AreEqual(3, results.Count(), "Expected 3 items back");
            Assert.AreEqual(1, rd.TypeRequestCount("MeNow"), "Expected MeNow to be requested once for the top level item");
            Assert.AreEqual(2, rd.TypeRequestCount("MasterHTMLRenderHTMLAndFurther"), "Expected two times recursing on this guy!");
            Assert.IsTrue(rd.addressesRequested.Contains("/PlotPageScanner=MeNow,Recursive=true,UseTopPage=true/http://www.bogus.com/dude.html"), "dude should be recursed once");
            Assert.IsTrue(rd.addressesRequested.Contains("/PlotPageScanner=MeNow,Recursive=true,UseTopPage=true/http://www.bogus.com/dude2.html"), "dude2 should have been recursed once as well");
        }

        [TestMethod]
        public void TestMTitlesResetCorrectly()
        {
            var target = new ScanThisPageAndBelow();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLPageScanners\\MasterPageWithSubPages.html") };
            Utilities.AddPart(laf);
            var rd = new DummyRender();
            rd.SetSubTitle = "Freak";
            Utilities.AddPart(rd);
            Utilities.Compose(target);

            var results = target.Render("/UseTopPage=false,Recursive=true,PlotPageScanner=MeNow/http://www.bogus.com/doit.html");
            var result = results.ToArray();
            Assert.IsTrue(result.All(p => p.GetMetadata<PivotMetadataString>("Note Title").All(pn => pn.Value == "Dude")), "Not all images have the right title!");
        }
    }
}
